package io.xdag.block;

import java.io.File;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import io.xdag.block.model.XdagBlock;
import io.xdag.block.model.XdagHash;
import io.xdag.file.XdagFile;
import io.xdag.utils.DateUtils;

public class BlockProcessor implements Runnable  {
	


	private final static long XDAG_MAIN_ERA = 0x16940000000L;
	private final static int XDAG_BLOCK_FIELDS = 16;
	private final static int MAX_LINKS = 15;

	private final static String BASE_PATH = System.getProperty("user.dir") + File.separator;

	public enum EXdagFieldType {
		XDAG_FIELD_NONCE(0), // 0
		XDAG_FIELD_HEAD(1), // 1
		XDAG_FIELD_IN(2), // 2
		XDAG_FIELD_OUT(3), // 3
		XDAG_FIELD_SIGN_IN(4), // 4
		XDAG_FIELD_SIGN_OUT(5), // 5
		XDAG_FIELD_PUBLIC_KEY_0(6), // 6
		XDAG_FIELD_PUBLIC_KEY_1(7), // 7
		XDAG_FIELD_HEAD_TEST(8), // 8
		XDAG_FIELD_RESERVE0(9), // 9
		XDAG_FIELD_RESERVE1(10), // 10
		XDAG_FIELD_RESERVE2(11), // 11
		XDAG_FIELD_RESERVE3(12), // 12
		XDAG_FIELD_RESERVE4(13), // 13
		XDAG_FIELD_RESERVE5(14), // 14
		XDAG_FIELD_RESERVE6(15); // 15

		private int iNum = 0;

		private EXdagFieldType(int iNum) {
			this.iNum = iNum;
		}

		public int getCode() {
			return this.iNum;
		}

	};

	public int addBlockNolock(XdagBlock newBlock, BigInteger limit) {
		long timestamp = DateUtils.getTimestamp();
		BigInteger sumIn = BigInteger.ZERO, sumOut = BigInteger.ZERO, psum;
		int keysCount = 0, ourKeysCount = 0;
		int signInCount = 0, signOutCount = 0;
		int signinmask = 0, signoutmask = 0,inmask = 0, outmask = 0, err = 0;
		// 根据区块类型获取每个field的状态
		for (int i = 1; i < XDAG_BLOCK_FIELDS; ++i) {
			int type = (int) newBlock.fields[0].data[1].get();

			switch (EXdagFieldType.class.getEnumConstants()[xdagType(type, i)]) {
			case XDAG_FIELD_NONCE:
				break;
			case XDAG_FIELD_IN:
				inmask |= 1 << i;//0001=1
				break;
			case XDAG_FIELD_OUT:
				outmask |= 1 << i;
				break;
			case XDAG_FIELD_SIGN_IN:
				// 检测signInCount是否为单数则更新mask
				if ((++signInCount & 1) > 0) {
					signinmask |= 1 << i;//0010=2
				}
				break;
			case XDAG_FIELD_SIGN_OUT:
				// 检测signOutCount是否为单数则更新mask
				if ((++signOutCount & 1) > 0) {
					signoutmask |= 1 << i;//0100=4
				}
				break;
			case XDAG_FIELD_PUBLIC_KEY_0:
			case XDAG_FIELD_PUBLIC_KEY_1:
				// if((public_keys[keysCount].key = xdag_public_to_key(newBlock->field[i].data,
				// type - XDAG_FIELD_PUBLIC_KEY_0))) {
				// public_keys[keysCount++].pub =
				// (uint64_t*)((uintptr_t)&newBlock->field[i].data | (type -
				// XDAG_FIELD_PUBLIC_KEY_0));
				// }
				break;

			case XDAG_FIELD_RESERVE0:
				break;

			case XDAG_FIELD_RESERVE1:
				break;

			case XDAG_FIELD_RESERVE2:
				break;

			case XDAG_FIELD_RESERVE3:
				break;

			case XDAG_FIELD_RESERVE4:
				break;

			case XDAG_FIELD_RESERVE5:
				break;

			case XDAG_FIELD_RESERVE6:
				break;

			default:
				err = 3;
				return err;
			}
		}
		//根据掩码获取block,不存在则返回；获取的区块时间大于当前时间返回；获取区块连接数大于等于最大连接数返回
		//获取密钥
		//处理块的签名
		//计算区块难度
		return 0;
	}

	/**
	 * 双sha256加密hash
	 * @param xdagBlock
	 * @return
	 */
	public static XdagHash xdagHash(XdagBlock xdagBlock){
		
		MessageDigest messageDigest;
		XdagHash xdagHash = new XdagHash();
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            byte[] bytes = new byte[xdagBlock.getByteBuffer().remaining()];
            xdagBlock.getByteBuffer().get(bytes, 0, bytes.length);
            byte[] hash = messageDigest.digest(bytes);
            byte[] hash2 = messageDigest.digest(hash);
            xdagHash.setByteBuffer(hash2);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } 
        return xdagHash;
	}
	/**
	 * xdagblock类型
	 * 每4位存储一个状态
	 * @param type
	 * @param i 当前第几状态位
	 * @return
	 */
	public int xdagType(int type, int i) {
		return type >> ((i) << 2) & 0xf;
	}

	/**
	 * 根据当前时间戳计算出周期总数，其中一个周期64秒
	 * 
	 * @return
	 */
	public static long xdagMainTime() {
		return DateUtils.getTimestamp() >> 16;
	}

	/**
	 * 根据开始时间戳计算出周期总数，其中一个周期64秒
	 * 
	 * @return
	 */
	public static long xdagStartMainTime() {
		return XDAG_MAIN_ERA >> 16;
	}

	/**
	 * 加载区块信息
	 * 
	 * @param startTime
	 *            创始区块开始时间戳
	 * @param endTime
	 *            当前时间错
	 */
	public static void xdagLoadBlocks(long startTime, long endTime) {
		long bufsize = 2048, todo = 0, mask = 0;
		XdagFile file = new XdagFile();
		while (startTime < endTime) {
			Object[] args = Storage.formatArgs(startTime, 4);
			String path = BASE_PATH + String.format(Storage.STORAGE_FILE, args);
			boolean fileExists = file.exists(path);
			// System.out.println(path);
			// System.out.println(fileExists);
			if (fileExists) {
				Byte[] bytes = file.readFile(path);
				XdagBlock xdagBlock = new XdagBlock(bytes);
				System.out.println(path);
				for (int i = 0; i < xdagBlock.getFields().length; i++) {
					for (int j = 0; j < xdagBlock.getFields()[i].getData().length; j++) {
						System.out.println("Fields:" + i + "," + xdagBlock.getFields()[i].getData()[j]);
					}
				}
				// break;
			} else {
				// System.out.println("vvvv");
			}
			if (todo != bufsize) {
				if (fileExists) {

				} else if (!fileExists) {
					mask = (1l << 16) - 1;
					// System.out.println(16);
				} else if (!file.exists(BASE_PATH + String.format(Storage.STORAGE_DIR3, args))) {
					mask = (1l << 16) - 1;
					// System.out.println(16);
				} else if (!file.exists(BASE_PATH + String.format(Storage.STORAGE_DIR2, args))) {
					mask = (1l << 24) - 1;
					// System.out.println(24);
				} else if (!file.exists(BASE_PATH + String.format(Storage.STORAGE_DIR1, args))) {
					mask = (1l << 32) - 1;
					// System.out.println(32);
				} else {
					mask = (1l << 40) - 1;
					// System.out.println(40);
				}

				startTime |= mask;
				startTime++;
				// System.out.println(endTime);
				// System.out.println(mask);
				// System.out.println(startTime);
			}
		}
	}

	
	@Override
	public void run() {
		//执行线程初始化
	}
	
	public static void main(String[] args) {

	}

}
